﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TangoGames.Scene;
using Microsoft.Xna.Framework;
using incubation_xna3d.Scene;

namespace incubation_xna3d.Enemies
{
    class EnemiesManager : GameComponent, IEnemiesManager
    {
        #region Fields

        /// <summary>
        /// Gerenciador da cena
        /// </summary>
        private ISceneManager sceneManager;

        /// <summary>
        /// Lista de inimigos
        /// </summary>
        List<IEnemie> enemiesList = new List<IEnemie>();

        /// <summary>
        /// Estados
        /// </summary>
        public enum EnemieManagerStates { AguardandoVez, Jogando }

        /// <summary>
        /// Estado atual
        /// </summary>
        EnemieManagerStates state;

        /// <summary>
        /// Inimigo ativo no turn
        /// </summary>
        int activeEnemie;

        /// <summary>
        /// Lista de pontos de spaw
        /// </summary>
        private List<Point> spawPoints = new List<Point>();

        /// <summary>
        /// Numero do último turno de spaw
        /// </summary>
        private int lastSpawTurn = 0;

        /// <summary>
        /// Quantidade de turnos para Spaw
        /// </summary>
        private int maxTurnsSpaw = 1;

        /// <summary>
        /// Quantidade máxima de inimigos
        /// </summary>
        private int maxSpawEnemies = 4;

        /// <summary>
        /// gerador randomicos
        /// </summary>
        private Random random;

        #endregion

        #region Properties

        /// <summary>
        /// Lista de inimigos
        /// </summary>
        public List<IEnemie> EnemiesList { get { return enemiesList; } set { enemiesList = value; } }

        /// <summary>
        /// Gerenciador da cena corrente
        /// </summary>
        public ISceneManager SceneManager { get { return sceneManager; } set { sceneManager = value; } }

        #endregion

        #region Constructor
        
        /// <summary>
        /// Função construtora
        /// </summary>
        /// <param name="sceneManager">Gerenciador da cena</param>
        public EnemiesManager(Game game, ISceneManager sceneManager):base(game)
        {
            this.sceneManager = sceneManager;
            game.Components.Add(this);

            //cria gerador de números randomicos
            int TheSeed = (int)DateTime.Now.Ticks;
            random = new Random(TheSeed);

            // Cria inimigos iniciais
            CreatesInitialEnemies();

            state = EnemieManagerStates.AguardandoVez;

        }


        #endregion

        #region Methods

        /// <summary>
        /// adiciona inimigo
        /// </summary>
        /// <param name="enemie"></param>
        public void AddEnemie(IEnemie enemy)
        {
            enemiesList.Add(enemy);
            enemy.SceneManager = sceneManager;
            sceneManager.TurnManager.TurnElements[TurnPlayer.AIPlayer1].Add((ITurnElement)enemy);
        }

        /// <summary>
        /// remover inimigo
        /// </summary>
        /// <param name="enemie"></param>
        public void RemoveEnemie(IEnemie enemy)
        {
            enemiesList.Remove(enemy);
            sceneManager.TurnManager.TurnElements[TurnPlayer.AIPlayer1].Remove((ITurnElement)enemy);
        }

        /// <summary>
        /// Cria inimigos iniciais
        /// </summary>
        public void CreatesInitialEnemies()
        {
            //Spaw Points
            spawPoints.Add(new Point(3, 3)); //canto superior esquerdo
            spawPoints.Add(new Point(20, 15)); //meio direita

            IEnemie enemy;

            //inimigo 2
            enemy = new RedMonster(Game, sceneManager.Camera);
            enemy.BoardPosition = new Point(10, 15);
            enemy.CenterPositionBoardSquare(sceneManager.PathMap);
            enemiesList.Add(enemy);
            enemy.SceneManager = sceneManager;

        }

        /// <summary>
        /// Inimigo Jogando o turno
        /// </summary>
        private void PlayingTurn()
        {
            if (!HowIsActive())
            {
                sceneManager.TurnManager.EndPlayerTurn();
                state = EnemieManagerStates.AguardandoVez;
                return;
            }

            //nenhum inimigo para movimentar (mas o turno esta ativo)
            if (activeEnemie == -1) return;

            //Inimigo para moviemntar
            IEnemie currentEnemie = enemiesList[activeEnemie];

            //o inimigo esta em ação
            if (!currentEnemie.IsIdle) return;

            //escolhe alvo
            ICharacter targetCharacter = currentEnemie.HowIsTarget(sceneManager.CharactersList);

            //ponto de origem
            Point source = currentEnemie.BoardPosition;

            //ponto destino
            Point targetPoint = targetCharacter.BoardPosition;

            //calcula caminho do inimigo até o alvo
            //List<Point> path = sceneManager.PathMap.FindPath(source, targetPoint, false);
            path = sceneManager.PathMap.FindPath(source, targetPoint, false);

            if (path.Count > currentEnemie.CurrentMovementPoints)
            {
                Point pointDest = path[currentEnemie.MovementPoints];
                currentEnemie.BoardPosition = pointDest;
                currentEnemie.MoveTo(sceneManager.PathMap, pointDest);
                currentEnemie.CurrentMovementPoints = 0;
                return;
            }

            if (path.Count > 1)
            {
                Point pointDest = path.Last();
                currentEnemie.BoardPosition = pointDest;
                currentEnemie.MoveTo(sceneManager.PathMap, pointDest);
                currentEnemie.CurrentMovementPoints -= (path.Count - 1);
                return;
            }

            if (currentEnemie.MovementPoints > 0 && currentEnemie.InRangeOfAttack( sceneManager.PathMap , targetCharacter) )
            {
                currentEnemie.Attack(sceneManager.PathMap, targetCharacter);
                return;
            }
            currentEnemie.CurrentMovementPoints = 0;
            return;
        }

        /// <summary>
        /// Verifica qual inimigo sera movimentado
        /// </summary>
        /// <returns></returns>
        private bool HowIsActive()
        {
            activeEnemie = -1;
            IEnemie ene;
            for (int i = 0 ; i < enemiesList.Count; i++ ) 
            {
                ene = enemiesList[i];
                if (!ene.IsIdle) {
                    activeEnemie = i;
                    return true;
                }
                if ( ene.CurrentMovementPoints > 0 && activeEnemie==-1 ) activeEnemie=i;
            }
            if (activeEnemie == -1) return false;
            else return true;
        }

        #endregion

        #region Update

        /// <summary>
        /// Update
        /// </summary>
        /// <param name="gameTime"></param>
        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            CheckEnemies();

            switch (state)
            {
                case EnemieManagerStates.AguardandoVez:
                    if (sceneManager.TurnManager.CurrentPlayer == TurnPlayer.AIPlayer1) state = EnemieManagerStates.Jogando;
                    break;
                case EnemieManagerStates.Jogando:
                    PlayingTurn();
                    break;
                default:
                    break;
            }
        }

        /// <summary>
        /// Verifica situação dos inimigos
        /// </summary>
        private void CheckEnemies()
        {
            int turns;
            List<IEnemie> temp = new List<IEnemie>();
            foreach (IEnemie enemy in enemiesList) if (enemy.IsDead) temp.Add(enemy);
            foreach (IEnemie enemy in temp)
            {
                enemiesList.Remove(enemy);
                enemy.SelfRemove();
            }

            //Spaw de inimigos
            if (maxSpawEnemies > enemiesList.Count )
            {
                if (lastSpawTurn == 0) lastSpawTurn = sceneManager.TurnManager.TurnNumber;
                turns = sceneManager.TurnManager.TurnNumber - lastSpawTurn;
                if (turns >= maxTurnsSpaw) SpawEnemies();
            }
        }

        private void SpawEnemies()
        {
            int spawIndex = random.Next(spawPoints.Count);  
            
            IEnemie enemie = new RedMonster(Game, sceneManager.Camera);
            enemie.BoardPosition = spawPoints[spawIndex];
            enemie.CenterPositionBoardSquare(sceneManager.PathMap);
            AddEnemie(enemie);
            lastSpawTurn = 0;
        }

        #endregion

        #region Draw
        #endregion

        //**************testes
        public bool teste = true;

        public List<Point> path;
        //*********************
    }
}
